/**
 * 
 */
package com.szgd.filter;

import com.szgd.license.LicenseClient;
import com.szgd.service.hiddenDanger.HiddenDangerService;
import com.szgd.service.personnel.PersonnelInfoService;
import com.szgd.service.project.BidService;
import com.szgd.service.project.ProjectService;
import com.szgd.service.project.SiteService;
import com.szgd.service.project.WorkSiteService;
import com.szgd.service.sys.LogService;
import com.szgd.service.sys.SysDictService;
import com.szgd.service.sys.UserService;
import com.szgd.util.Constant;
import com.szgd.util.RequestHelp;
import com.szgd.util.TimeUtil;
import com.szgd.util.UserUtil;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.Exception.ExpiredException;
import org.springframework.security.Exception.NoLicenseException;
import org.springframework.security.Exception.NoLocalMachineCodeException;
import org.springframework.security.authentication.AuthenticationServiceException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.web.WebAttributes;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.util.TextEscapeUtils;

import java.io.File;
import java.io.InputStream;
import java.net.URL;
import java.util.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;


/**
 * @author linxh
 *
 */
public class ValidateAuthenticationFilter extends
        UsernamePasswordAuthenticationFilter {
	private static Logger logger = LoggerFactory.getLogger(ValidateAuthenticationFilter.class);

	private boolean postOnly = true;
	private boolean allowEmptyValidateCode = false;
	private String sessionvalidateCodeField = Constant.VALIDATE_CODE_NAME;
	private String validateCodeParameter = Constant.VALIDATE_CODE_NAME;

	@Autowired
	private UserService userService;
	@Autowired
	private SysDictService sysDictService;
	@Autowired
	private WorkSiteService workSiteService;
	@Autowired
	private ProjectService projectService;
	@Autowired
	private HiddenDangerService hiddenDangerService;
	@Autowired
	SiteService siteService;
	@Autowired
	BidService bidService;
	@Autowired
	LicenseClient licenseClient;
	@Autowired
	LogService logService;

	@Override
	public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
		if (postOnly && !request.getMethod().equals("POST")) {
			throw new AuthenticationServiceException("Authentication method not supported: " + request.getMethod());
		}
		String username = obtainUsername(request);
		String password = obtainPassword(request);
		if (username == null) {
			username = "";
		}
		if (password == null) {
			password = "";
		}
		username = username.trim();
		com.szgd.bean.User sysUser = userService.getUserByLoginId(username);
		UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(username, password);
		// Place the last username attempted into HttpSession for views
		HttpSession session = request.getSession(false);
		if (session != null || getAllowSessionCreation()) {
			request.getSession().setAttribute(	SPRING_SECURITY_LAST_USERNAME_KEY,
												TextEscapeUtils.escapeEntities(username));
		}
		// Allow subclasses to set the "details" property
		setDetails(request, authRequest);
		// check validate code
		if (!isAllowEmptyValidateCode())
			checkValidateCode(request);
		checkLicense(request);//验证许可证
		Authentication aut = this.getAuthenticationManager().authenticate(authRequest);
		if(aut.getPrincipal() !=null ){
			 User user = (User) aut.getPrincipal();
			 if(user.getUsername() != null){
				 user.setLoginIP(RequestHelp.getRemoteHost(request));
				 //List<Group> groupList = identityService.createGroupQuery().groupMember(UserUtil.getUserFromSession(session)).list();
			        List<String> gList = new ArrayList<String>();
			        /*for(Group g : groupList){
			        	gList.add(g.getId());
			        }*/

				 Map<String, Object> userParentDeptMap = userService.getUserParentDept(username);
				 String userParentDeptParentId = userParentDeptMap.get("DEPT_PARENT_ID") == null ? "0" : String.valueOf(userParentDeptMap.get("DEPT_PARENT_ID"));
				 Map<String, Object> userDeptMap = new HashMap<>();
				 if(userParentDeptParentId.equals("0")){
					 userDeptMap.put("DEPT_CD" , user.getDeptCd());
					 userDeptMap.put("DEPT_NAME" , user.getDeptName());
				 }else{
					 userDeptMap.put("DEPT_CD" , userParentDeptMap.get("DEPT_CD"));
					 userDeptMap.put("DEPT_NAME" , userParentDeptMap.get("DEPT_NAME"));
				 }
				 request.getSession().setAttribute("userDeptMap", userDeptMap);
				 System.out.println(request.getSession().getAttribute(WebAttributes.AUTHENTICATION_EXCEPTION));
				 request.getSession().removeAttribute(WebAttributes.AUTHENTICATION_EXCEPTION);
			     request.getSession().setAttribute("userInfo", user.toHashMap());
				 request.getSession().setAttribute(user.getUsername(), gList);
				 request.getSession().setAttribute(UserUtil.USERINFOMATION,user);
				 sysDictService.setAllParentChildMap(session);
				 workSiteService.setAllWorkSite(session);
				 projectService.setAllProject(session);
				 siteService.setAllSite(session);
				 bidService.setAllBid(session);
				 userService.setUserBid(session);
				hiddenDangerService.setTaskCount(session,user.getRoleIds());
				 logger.debug("user login success::"+user.getUsername());
                 insertLog(user.getLoginId(),user.getUserCnName());
			 }
		}
		return aut;
	}

	/**
	 * 
	 * <li>比较session中的验证码和用户输入的验证码是否相等</li>
	 * 
	 */
	protected void checkValidateCode(HttpServletRequest request) {
		/*String sessionValidateCode = obtainSessionValidateCode(request);
		String validateCodeParameter = obtainValidateCodeParameter(request);
		if (StringUtils.isEmpty(validateCodeParameter) || !sessionValidateCode.equalsIgnoreCase(validateCodeParameter)) {
			throw new AuthenticationServiceException("ERROR_3");
		}*/
		//暂时不实用验证码
	}


	protected void insertLog(String loginId,String loginName)
	{
        Map<String, Object> paramsMap  = new HashMap<>();
        paramsMap.put("opLoginId",loginId);
        paramsMap.put("opName",loginName);
        paramsMap.put("menuId","LOGIN_IN");
        paramsMap.put("menuName","登录系统");
        paramsMap.put("sysFlag","1");
        paramsMap.put("opTime", TimeUtil.formatTime(new Date()));
		paramsMap.put("creator",loginId);
        logService.insertLog(paramsMap);
	}

	/**
	 * 验证license
	 * @param request
	 */
	protected void checkLicense(HttpServletRequest request) {
		int license_state = userService.getLicenseState();

		URL url = this.getClass().getClassLoader().getResource("application.license");
		if (url == null)
		{
			throw new NoLicenseException("没有许可license文件！");
		}
		String filePath = url.getPath();//获取文件路径

		//licenseClient.validateLicense(new File(filePath));
		if (license_state/*licenseClient.getLicense_state()*/==LicenseClient.STATE_CODEERR)
		{
			throw new NoLocalMachineCodeException("在非许可的机器上运行");
		}else
		if (license_state/*licenseClient.getLicense_state()*/==LicenseClient.STATE_TIMEOUT)
		{
			throw new ExpiredException("许可证过期");
		}

	}

	private String obtainValidateCodeParameter(HttpServletRequest request) {
		return request.getParameter(validateCodeParameter);
	}

	protected String obtainSessionValidateCode(HttpServletRequest request) {
		Object obj = request.getSession().getAttribute(sessionvalidateCodeField);
		return null == obj ? "" : obj.toString();
	}

	public boolean isPostOnly() {
		return postOnly;
	}

	@Override
	public void setPostOnly(boolean postOnly) {
		this.postOnly = postOnly;
	}

	public String getValidateCodeName() {
		return sessionvalidateCodeField;
	}

	public void setValidateCodeName(String validateCodeName) {
		this.sessionvalidateCodeField = validateCodeName;
	}

	public boolean isAllowEmptyValidateCode() {
		return allowEmptyValidateCode;
	}

	public void setAllowEmptyValidateCode(boolean allowEmptyValidateCode) {
		this.allowEmptyValidateCode = allowEmptyValidateCode;
	}

}
